package com.spit.fammo.viewmodel

import android.view.View
import androidx.databinding.ObservableField
import androidx.databinding.ObservableInt
import androidx.fragment.app.Fragment
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.ToastUtils
import com.spit.amoeba.base.MyBaseViewModel
import com.spit.amoeba.bean.db.UploadOrderBean
import com.spit.amoeba.bean.db.UploadOrderListBean
import com.spit.fammo.R
import com.spit.fammo.bean.db.AssetBean
import com.spit.fammo.bean.db.StockTakeListBean
import com.spit.fammo.ext.ASSET_STOCK_PAGE
import com.spit.fammo.ext.STOCK_TAKE_LIST_PAGE
import com.spit.fammo.ext.UPLOAD_IMAGE_SPLIT
import com.spit.fammo.ext.showMessage
import com.spit.fammo.network.apiService
import com.spit.fammo.network.stateCallback.ListDataUiState
import com.spit.fammo.util.CacheUtil
import com.spit.fammo.util.ImageUtils
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.hgj.jetpackmvvm.base.appContext
import me.hgj.jetpackmvvm.callback.databind.BooleanObservableField
import me.hgj.jetpackmvvm.callback.databind.IntObservableField
import me.hgj.jetpackmvvm.callback.databind.StringObservableField
import me.hgj.jetpackmvvm.ext.requestNoCheck
import org.json.JSONArray
import org.json.JSONObject
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
 * User: Nike
 *  2024/12/19 15:14
 */
class AssetModel: MyBaseViewModel() {

    var changeEpc = StringObservableField()

    var listJsonArray: MutableLiveData<JSONArray> = MutableLiveData()

    var changeEpcSuccess: MutableLiveData<AssetBean> = MutableLiveData()

    var remarks = StringObservableField()

    val epc = StringObservableField()

    var epcAssetUploadData: MutableLiveData<AssetBean> = MutableLiveData()
    var epcListAssetUploadData: MutableLiveData<List<AssetBean>> = MutableLiveData()
    var epcListAssetUploadFailData: MutableLiveData<List<AssetBean>> = MutableLiveData()
    var uploadMainDrawer: MutableLiveData<Boolean> = MutableLiveData()

    val orderId = StringObservableField()

    var listBean: MutableLiveData<ListDataUiState<StockTakeListBean>> = MutableLiveData()
    var listAssetBean: MutableLiveData<ArrayList<AssetBean>> = MutableLiveData()

    var assetStatus = IntObservableField()
    var statusText = object : ObservableField<String>(assetStatus){
        override fun get(): String {
            return if(assetStatus.get() == ASSET_STOCK_PAGE){
                appContext.getString(R.string.in_library)
            }else{
                appContext.getString(R.string.missing)
            }
        }
    }
    var statusColor = object : ObservableField<Int>(assetStatus){
        override fun get(): Int {
            return if(assetStatus.get() == 2){
                R.color.colorAccent
            }else{
                R.color.red_ff0000
            }
        }
    }

    val isEpcVisible = BooleanObservableField()
    var epcVisible = object :ObservableInt(isEpcVisible){
        override fun get(): Int {
            return if(isEpcVisible.get()){
                View.GONE
            }else{
                View.VISIBLE
            }
        }
    }

    fun onRequestText(bean: String?) {
        val bean = JSONObject(bean)
        Flowable.fromCallable {
            val list = JSONArray()

            var objTitle1 = JSONObject()
            objTitle1.put("title", appContext.getString(R.string.asset_information))
            val array1 = JSONArray()

            var objTitle2 = JSONObject()
            objTitle2.put("title", appContext.getString(R.string.financial_information))
            val array2 = JSONArray()

            var objTitle3 = JSONObject()
            objTitle3.put("title", appContext.getString(R.string.tag_information))
            val array3 = JSONArray()

            var objTitle4 = JSONObject()
            objTitle4.put("title", appContext.getString(R.string.cert_information))
            val array4 = JSONArray()

            val headerkeys: Iterator<String> = bean.keys()
            while (headerkeys.hasNext()) {
                val headerkey = headerkeys.next()
                if (headerkey == null) {
                    continue
                }
                val headerValue: String? = bean.getString(headerkey)

                fun addToJSONObject(array: JSONArray, key: String, titleResId: Int) {
                    val obj = JSONObject()
                    obj.put("keys", key)
                    obj.put("title", appContext.getString(titleResId))
                    obj.put("content", if (headerValue == "null" || headerValue.isNullOrEmpty()) "-" else headerValue)
                    array.put(obj)
                }

                when (headerkey) {
                    "assetCode", "assetno", "name", "brand", "model", "serial", "unit", "spaceType",
                    "spaceLoc", "categoryName", "otherLoc", "deptName","assetType",
                    "lastStockDate", "createdByname", "createdDate", "possessor", "usergroup", "lastassetno" -> {
                        val titleResId = when (headerkey) {
                            "assetno" -> R.string.system_number
                            "name" -> R.string.assetname
                            "assetCode" -> R.string.item_code
                            "brand" -> R.string.brand
                            "model" -> R.string.model
                            "assetType" -> R.string.item_type
                            "serial" -> R.string.serial_number
                            "unit" -> R.string.unit
                            "deptName" -> R.string.subordinate_department
                            "spaceLoc" -> R.string.spatial_position
                            "categoryName" -> R.string.category
                            "otherLoc" -> R.string.other_position
                            "lastStockDate" -> R.string.last_stock_date
                            "createdByname" -> R.string.created_by
                            "createdDate" -> R.string.create_date
                            "possessor" -> R.string.holder
                            "usergroup" -> R.string.group
                            "lastassetno" -> R.string.prosecution_no
                            else -> throw IllegalArgumentException(headerkey + " Unknown headerkey")
                        }
                        addToJSONObject(array1, headerkey, titleResId)
                    }

                    "purchaseDate", "invoiceDate", "invoiceNo", "fundingSourcename", "supplier", "maintenanceDate", "cost",
                    "praticalValue", "estimatedLifetime" -> {
                        val titleResId = when (headerkey) {
                            "purchaseDate" -> R.string.purchase_date
                            "invoiceDate" -> R.string.invoice_voucher_date
                            "invoiceNo" -> R.string.invoice_voucher_no
                            "fundingSourcename" -> R.string.funding_source
                            "supplier" -> R.string.supplier
                            "maintenanceDate" -> R.string.maintenance_date
                            "cost" -> R.string.cost
                            "praticalValue" -> R.string.practical_value
                            "estimatedLifetime" -> R.string.estimated_lifetime_month
                            else -> throw IllegalArgumentException("Unknown headerkey")
                        }
                        addToJSONObject(array2, headerkey, titleResId)
                    }

                    "typeOfTag", "barcode", "epc", "newEpc", "statusid", "scanTime", "scanStatus", "remarks" -> {
                        val titleResId = when (headerkey) {
                            "statusid" -> R.string.status
                            "typeOfTag" -> R.string.type_of_tag
                            "barcode" -> R.string.barcode
                            "epc" -> R.string.epc
                            "newEpc" -> R.string.new_epc
                            "scanStatus" -> R.string.scan_status
                            "scanTime" -> R.string.scan_time
                            "remarks" -> R.string.remark
                            else -> throw IllegalArgumentException(headerkey + " Unknown headerkey")
                        }
                        addToJSONObject(array3, headerkey, titleResId)
                    }

                    //, "isverified"
                    "certType", "certUrl", "cerstatus", "startdate", "enddate" -> {
                        val titleResId = when (headerkey) {
                            "certType" -> R.string.certificate_type
                            "certUrl" -> R.string.cert_url
                            "cerstatus" -> R.string.cert_status
                            "startdate" -> R.string.valid_date
                            "enddate" -> R.string.valid_date
                            "isverified" -> R.string.valid_date
                            else -> throw IllegalArgumentException("Unknown headerkey")
                        }
                        addToJSONObject(array4, headerkey, titleResId)
                    }

                    else -> continue
                }
            }

            val headerKeys1 = listOf(
                "assetno", "assetCode", "name", "assetType", "brand", "model", "serial", "spaceLoc", "deptName"
            )
            val tempMap = mutableMapOf<String, JSONObject>()
            for (i in 0 until array1.length()) {
                val obj = array1.getJSONObject(i)
                val key = obj.getString("keys")
                tempMap[key] = obj
            }
            val newArray1 = JSONArray()
            for (headerkey in headerKeys1) {
                val obj = tempMap[headerkey]
                if (obj != null) {
                    newArray1.put(obj)
                }
            }
            objTitle1.put("list", newArray1)
//            objTitle1.put("list", array1)
            objTitle2.put("list", array2)
            objTitle3.put("list", array3)
            objTitle4.put("list", array4)



            val list4 = objTitle4.optJSONArray("list")
            if (list4 != null && list4.length() >= 5) {
                val item1 = list4.optJSONObject(0)//certType
                val item2 = list4.optJSONObject(1)//certUrl
                val item3 = list4.optJSONObject(2)//cerstatus
                val item4 = list4.optJSONObject(3)//startdate
                val item5 = list4.optJSONObject(4)//enddate
                var enddate = item4.optString("content")
                var startdate = item5.optString("content")
                val startdateList = startdate.split(",")
                val enddateList = enddate.split(",")

                if (startdateList.size == enddateList.size) {
                    val result = StringBuilder()
                    for (i in startdateList.indices) {
                        result.append(startdateList[i])
                        result.append(" - ")
                        result.append(enddateList[i])
                        if (i < startdateList.size - 1) {
                            result.append(",")
                        }
                    }
                    startdate = result.toString()
                } else {
                    startdate = "$startdate-$enddate"
                }

                item4.put("content", startdate)
                list4.remove(list4.length() - 1)
                list4.put(0, item2)
                list4.put(1, item3)
                list4.put(2, item1)

                val optList = objTitle4.optJSONArray("list")
                val certTypeList = optList.getJSONObject(0).getString("content").split(",")
                val certUrlList = optList.getJSONObject(1).getString("content").split(",")
                val cerStatusList = optList.getJSONObject(2).getString("content").split(",")
                val endDateList = optList.getJSONObject(3).getString("content").split(",")

                val newJsonArray = JSONArray()
                for (i in certTypeList.indices) {
                    val newCert = JSONObject().apply {
                        put("keys", "certType")
                        put("title", appContext.getString(R.string.certificate_type))
                        put("content", certTypeList[i])
                    }
                    newJsonArray.put(newCert)

                    val newCertUrl = JSONObject().apply {
                        put("keys", "certUrl")
                        put("title", appContext.getString(R.string.cert_url))
                        put("content", certUrlList[i])
                    }
                    newJsonArray.put(newCertUrl)

                    val newCerStatus = JSONObject().apply {
                        put("keys", "cerstatus")
                        put("title", appContext.getString(R.string.cert_status))
                        put("content", cerStatusList[i])
                    }
                    newJsonArray.put(newCerStatus)

                    val newEndDate = JSONObject().apply {
                        put("keys", "enddate")
                        put("title", appContext.getString(R.string.valid_date))
                        put("content", endDateList[i])
                    }
                    newJsonArray.put(newEndDate)

                    if (endDateList.size > 1 && i != endDateList.lastIndex) {
                        val newNewCert = JSONObject().apply {
                            put("keys", "")
                            put("title", "")
                            put("content", "")
                        }
                        newJsonArray.put(newNewCert)
                    }
                }

                objTitle4.put("list", newJsonArray)
            }

            list.put(objTitle1)
//            list.put(objTitle2)
            list.put(objTitle3)
//            list.put(objTitle4)

            list
        }.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({ list ->
                listJsonArray.value = list
            }, { error ->
                // 处理错误
                LogUtils.e(error)
            })

    }

    fun onUpload(frg: Fragment) {
        viewModelScope.launch(Dispatchers.IO) {
            val list = assetDao.findById(orderId.get(), userId)
            if (list.isNullOrEmpty()) {
                withContext(Dispatchers.Main) {
                    frg.showMessage(message = appContext.getString(R.string.no_data))
                }
                return@launch
            }
            loadingChange.showDialog.postValue("Save...")
            var uploadOrderBean = uploadOrderDao.findType(STOCK_TAKE_LIST_PAGE)
            if (uploadOrderBean == null) {
                uploadOrderBean = UploadOrderBean()
                uploadOrderBean.type = STOCK_TAKE_LIST_PAGE
                uploadOrderBean.name = appContext.getString(R.string.stock_take)
                uploadOrderBean.userId = userId!!
                uploadOrderDao.add(uploadOrderBean)
            }

            var bean = uploadOrderListDao.findById(orderId = orderId.get())
            if (bean != null) {
                uploadOrderListDao.deleteById(bean.orderId)
            }
            bean = UploadOrderListBean()
            val jsonArray = JSONArray()
            bean.userId = userId
            bean.orderId = orderId.get()
            bean.name = name.get()
            bean.type = uploadOrderBean.type
            list.forEachIndexed { index, bean ->
                val obj = JSONObject()
                obj.put("loginID", userId)
                obj.put("userName", CacheUtil.getUser()!!.LoginID)
                obj.put("orderNo", orderId.get())
                obj.put("AssetNo", bean.assetno)
                obj.put("ScanDate", bean.scanTime)
                obj.put("QRCode", "")
                obj.put("EPC", bean.epc)
                obj.put("Remarks", bean.remarks)
                obj.put("statusID", bean.type)
                obj.put("FoundStatus", bean.scanStatus)

                val imageList = bean.pic
                if (imageList != null) {
                    val split = imageList!!.split(UPLOAD_IMAGE_SPLIT)
                    val sb = StringBuffer()
                    split.forEachIndexed() { index, s ->
                        if (!StringUtils.isEmpty(s)) {
                            val imageToBase64 = ImageUtils.imageToBase64(s)
                            sb.append(imageToBase64).append(UPLOAD_IMAGE_SPLIT)
                        }
                    }
                    obj.put("img", sb.toString())
                }
                jsonArray.put(obj)
            }
            bean.data = jsonArray.toString()
            uploadOrderListDao.add(bean)

            val stockTakeListBean = stockTakeListDao.findById(orderId.get())
            stockTakeListBean.lastUpdate = TimeUtils.getNowString()
            stockTakeListDao.insertOrUpdate(stockTakeListBean)

            withContext(Dispatchers.Main) {
//                runBlocking {
//                    delay(3000) // 延迟1秒钟
//                    loadingChange.dismissDialog.value = true
//                }
                loadingChange.dismissDialog.value = true
                frg.showMessage(message = appContext.getString(R.string.upload_tips))
                uploadMainDrawer.value = true
            }
        }

    }

    fun onStockTakeList() {
        if (NetworkUtils.isConnected()){
            requestNoCheck({ apiService.stockTakeList() }, {
                viewModelScope.launch(Dispatchers.IO) {
                    stockTakeListDao.deleteAll()
                    val nowString = TimeUtils.getNowString(TimeUtils.getSafeDateFormat("dd/MM/yyyy"))
                    val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())
                    val itemsWithDates: List<Pair<StockTakeListBean, Date>> = it.mapNotNull {
                        try {
                            it to dateFormat.parse(it.endDate)
                        } catch (e: ParseException) {
                            null
                        }
                    }
                    val sortedItems = itemsWithDates.sortedByDescending { it.second }
                    val nowDate: Date = dateFormat.parse(nowString)
                    sortedItems.forEach { (item, validDate) ->
                        if (validDate.compareTo(nowDate) >= 0) {
                            item.userId = userId
                            item.companyid = companyID
                            stockTakeListDao.add(item)
                        }
                    }
                    var all = stockTakeListDao.findAll(userId)
                    withContext(Dispatchers.Main) {
                        listBean.value = ListDataUiState(
                            isSuccess = true,
                            isRefresh = true,
                            listData = all as ArrayList<StockTakeListBean>,
                            pageSize = all.size,
                            isFirstEmpty = if (all!!.size == 0) true else false
                        )
                    }
                }
            }, {
                //请求失败 网络异常回调在这里
                loadingChange.dismissDialog
                ToastUtils.showShort(it.throwable!!.message)
                LogUtils.e(it.throwable)
            }, false)
        }else{
            onStockTakeListOffice()
        }

    }

    fun onStockTakeListOffice(){
        viewModelScope.launch(Dispatchers.IO) {
            val all = stockTakeListDao.findAll(userId)
            listBean.postValue(
                ListDataUiState(
                    isSuccess = true,
                    isRefresh = true,
                    listData = all as ArrayList<StockTakeListBean>,
                    pageSize = all.size,
                    isFirstEmpty = if (all!!.size == 0) true else false
                ))
        }
    }

    fun onRequest(type: Int) {
        viewModelScope.launch(Dispatchers.IO) {
            var list: List<AssetBean>
            if (type == -1){
                list = assetDao.findAll(orderId.get(), userId)
            }else{
                list = assetDao.findAll(orderId.get(), type, userId)
            }
            listAssetBean.postValue(list as ArrayList)
        }
    }
}